#include "SingleWireSerial/SingleWireSerial.h"


#include "debug.h"
#define LOG_TAG "[SWS]"

/** */
struct SingleWireSerial
{
    u8 rxData[16];
    u16 rxLen;
    u8 rxByteBitCount;
    u8 remainBitCount;
    u16 bitNum;
    u8  bitFillCount;
    int timer_handle;
    u32 captureOffset;
    u32 BitPeriod_us;
    u32 scanGap_inFreeState_us;
    u8 (*getValue)(void);
    SingleWireSerial_PostHandler_t RxpostHandler;
    SingleWireSerial_TriggerDectectHandler_t Detector;
    void *DetectorPrivate;
};

static struct SingleWireSerial *tid_to_handle[6]; //将tid转为handle

__attribute__((used)) static void SingleWireSerial_FreeHandler(int tid)
{
    struct SingleWireSerial *self = tid_to_handle[tid];
    if(self == NULL) return;
    if(self->Detector(self->DetectorPrivate) == true)
    {
        SingleWireSerial_StartRecieve(self);
    }
    return;
}

SingleWireSerial_Handle_t SingleWireSerial_CreateHandle(u16 bitNums,u8 captureOffsetPercent, 
                                                        u32 BitPeriod_us,
                                                        SingleWireSerial_PostHandler_t postHandler,
                                                        SingleWireSerial_TriggerDectectHandler_t detectorHandler,
                                                        void * dectectorPriv,
                                                        u8 (*getValueCB)(void),
                                                        u32 scanGap_inFreeState_us)
{
    struct gptimer_config timer_config = 
    {
        .irq_cb = SingleWireSerial_FreeHandler,
        .irq_priority = 2,
        .tid = -1
    };
    if(!detectorHandler)
    {
        return NULL;
    }
    if(!getValueCB)
    {
        return NULL;
    }
    struct SingleWireSerial* ret = zalloc(sizeof(struct SingleWireSerial));
    if(ret)
    {
        ret->bitNum = bitNums;
        ret->bitFillCount = bitNums % 8;
        ret->BitPeriod_us = BitPeriod_us;
        ret->captureOffset = (captureOffsetPercent * BitPeriod_us) / 100;
        ret->RxpostHandler = postHandler;
        ret->Detector = detectorHandler;
        ret->DetectorPrivate = dectectorPriv;
        ret->getValue = getValueCB;
        ret->scanGap_inFreeState_us = scanGap_inFreeState_us;

        timer_config.resolution_us = scanGap_inFreeState_us;
        ret->timer_handle = gptimer_init(&timer_config);
        logln_info("tid:%d",ret->timer_handle);
        if(ret->timer_handle != -1)
        {
            tid_to_handle[ret->timer_handle] = ret;
            gptimer_start(ret->timer_handle);
        }
        else
        {
            free(ret);
            ret = NULL;
        }
    }
    
    return (SingleWireSerial_Handle_t)ret;
}

void SingleWireSerial_DestroyHandle(SingleWireSerial_Handle_t handle)
{
    if(!handle)
    {
        return;
    }
    int tid = ((struct SingleWireSerial*)handle)->timer_handle;
    gptimer_pause(tid);
    gptimer_deinit(tid);
    free(handle);
}

static void SingleWireSerial_CaptureHandler(int tid)
{
    struct SingleWireSerial *sws = tid_to_handle[tid];
    u8 ByteIndex = sws->rxLen;
    u8 value;
    sws->rxData[ByteIndex] <<= 1;
    value = sws->getValue();
    if(value)
    {
        sws->rxData[ByteIndex] |= 0x01;
    }
    else
    {
        sws->rxData[ByteIndex] &= ~0x01;
    }
    sws->rxByteBitCount++;
    if(sws->rxByteBitCount == 8)
    {
        sws->rxByteBitCount = 0;
        sws->rxLen++;
    }
    sws->remainBitCount--;
    // printf("remain: %d,value:%u\n",sws->remainBitCount,value);
    if(sws->remainBitCount == 0)
    {
        
        if(sws->bitFillCount != 0)
        {
            sws->rxLen++;
            sws->rxData[ByteIndex] <<= sws->bitFillCount;
        }
        if(sws->RxpostHandler != NULL)
        {
            sws->RxpostHandler(sws,sws->rxData,sws->rxLen);
        }
        //定时器空闲,等待下次触发
        gptimer_set_resolution(tid,sws->scanGap_inFreeState_us);
        gptimer_set_irq_callback(tid,SingleWireSerial_FreeHandler);
    }
}

static void SingleWireSerial_StartCapture(int tid)
{
    // gptimer_set_count(tid,0);
    SingleWireSerial_CaptureHandler(tid);
    gptimer_set_resolution(tid,tid_to_handle[tid]->BitPeriod_us);
    gptimer_set_irq_callback(tid, SingleWireSerial_CaptureHandler);
}



void SingleWireSerial_StartRecieve(SingleWireSerial_Handle_t handle)
{
    struct SingleWireSerial* sws = (struct SingleWireSerial*)handle;
    if(!sws)
    {
        return;
    }
    int tid = sws->timer_handle;
    sws->rxLen = 0;
    sws->rxByteBitCount = 0;
    sws->remainBitCount = sws->bitNum;
    // log_info("Offset:%u\n",sws->captureOffset);
    gptimer_set_resolution(tid,sws->captureOffset);
    // gptimer_set_count(tid,0);logln_pos();
    gptimer_set_irq_callback(tid,SingleWireSerial_StartCapture);
}
